import requests
import json
import os
import asyncio
import aiohttp

# 接口地址(主)
_api_url="http://14.103.236.44:18001/api/ai/detect"
# 接口地址(备)
#_api_url_backup="http://116.204.115.87:19001/api/ai/detect"


_detect_static_enum_dict = {
    # 英文放到中文前面，中文放到英文后面
    "001fire": "001火灾检测",
    "002garbage": "002垃圾检测",
    "003faceDetect": "003人脸检测",
    "004callPhone": "004打电话识别",
    "005fight": "005人员打架",
    "006safeHat": "006安全帽识别",
    "007smoke": "007吸烟识别",
    "008walkerMan": "008行人识别",
    "009maskDetect": "009口罩检测",
    "010fallDetect": "010人员跌倒识别",
    "011crossFenceDetect": "011翻越围栏识别",
    "012streetVendorDetect": "012街头流动商贩识别"
}


def upload_image_for_detection(image_path, model_code="003faceDetect"):
    """
    上传图片到AI检测接口并获取检测结果
    
    参数:
        image_path (str): 图片文件的路径
        api_url (str): AI检测接口的URL
        model_code (str): 模型编码，
    
    返回:
        dict: 检测结果的JSON对象
    """
    try:
        # 检查图片文件是否存在
        if not os.path.exists(image_path):
            print(f"错误: 图片文件不存在 - {image_path}")
            return None
        
        print(f"正在上传图片: {image_path}")
        print(f"目标API: {_api_url}")
        print(f"使用模型编码: {model_code}")
        
        # 准备文件数据
        with open(image_path, 'rb') as f:
            files = {
                'file': (os.path.basename(image_path), f, 'image/jpeg')
            }
            
            # 表单数据，使用model_code参数
            data = {
                'model_code': model_code  # 模型编码参数
            }
            
            # 发送POST请求
            response = requests.post(_api_url, files=files, data=data)
            
            # 检查响应状态
            response.raise_for_status()
            
            # 尝试解析JSON响应
            try:
                result = response.json()
                return result
            except json.JSONDecodeError:
                print(f"警告: 无法解析响应为JSON，原始响应内容: {response.text}")
                return {"raw_response": response.text}
                
    except requests.exceptions.RequestException as e:
        print(f"请求出错: {e}")
        return None
    except Exception as e:
        print(f"发生错误: {e}")
        return None

def print_detection_result(result):
    """
    打印检测结果
    
    参数:
        result (dict): 检测结果的JSON对象
    """
    if not result:
        print("没有有效的检测结果")
        return
    
    # 美化打印JSON结果
    print("\n检测结果:")
    print(json.dumps(result, ensure_ascii=False, indent=2))
    
    # 如果有检测结果，尝试提取关键信息
    if isinstance(result, dict):
        # 打印基本信息
        if 'original_url' in result:
            print(f"\n原始图片URL: {result['original_url']}")
        
        if 'detected_url' in result:
            print(f"检测结果URL: {result['detected_url']}")
        
        # 打印图片尺寸
        if 'image_size' in result:
            size = result['image_size']
            print(f"图片尺寸: {size.get('width', 0)}x{size.get('height', 0)}")
        elif 'width' in result and 'height' in result:
            print(f"图片尺寸: {result['width']}x{result['height']}")
        
        # 打印使用的模型信息
        if 'model_used' in result:
            model_info = result['model_used']
            if isinstance(model_info, dict):
                print(f"使用模型: {model_info.get('name', '未知')} ({model_info.get('code', 'unknown')})")
                if model_info.get('is_fallback', False):
                    print("提示: 由于指定模型不可用，系统自动使用了备选模型")
            else:
                print(f"使用模型: {model_info}")
        
        # 打印消息
        if 'message' in result:
            print(f"\n消息: {result['message']}")
        
        # 打印检测到的目标
        if 'detections' in result:
            detections = result['detections']
            print(f"\n检测到的目标数量: {len(detections)}")
            
            # 打印每个检测目标的详细信息
            for i, detection in enumerate(detections):
                print(f"\n目标 {i+1}:")
                if 'class' in detection:
                    print(f"  类别: {detection['class']}")
                if 'confidence' in detection:
                    print(f"  置信度: {detection['confidence']:.2f}")
                if 'bbox' in detection:
                    bbox = detection['bbox']
                    print(f"  边界框: xmin={bbox.get('xmin', 0)}, ymin={bbox.get('ymin', 0)}, "
                          f"xmax={bbox.get('xmax', 0)}, ymax={bbox.get('ymax', 0)}")

def detect_and_save_result(image_path, model_code="003faceDetect", save_json=True):
    """
    检测图片并可选保存结果到JSON文件
    
    参数:
        image_path (str): 图片路径
        model_code (str): 模型编码
        save_json (bool): 是否保存结果到JSON文件
    
    返回:
        dict: 检测结果
    """
    # 调用API进行检测
    detection_result = upload_image_for_detection(image_path, model_code=model_code)
    
    # 打印检测结果
    print_detection_result(detection_result)
    
    # 保存结果到JSON文件
    if save_json and detection_result:
        # 生成保存文件名
        base_name = os.path.splitext(os.path.basename(image_path))[0]
        if not os.path.exists("./detect_out"):
            os.makedirs("./detect_out", exist_ok=True)
        json_file = f".\detect_out\detection_result_{base_name}.json"
        
        # 保存JSON文件
        with open(json_file, 'w', encoding='utf-8') as f:
            json.dump(detection_result, f, ensure_ascii=False, indent=2)
        
        # 根据模型类型显示不同的保存消息
        if model_code == "003faceDetect":
            print(f"\n人脸检测结果已保存到: {json_file}")
        elif model_code == "002garbage":
            print(f"\n垃圾检测结果已保存到: {json_file}")
        elif model_code == "001fire":
            print(f"\n火灾检测结果已保存到: {json_file}")
        else:
            print(f"\n检测结果已保存到: {json_file}")
    
    # 根据模型类型显示不同的完成消息
    if model_code == "003faceDetect":
        print("\n人脸检测完成")
    elif model_code == "002garbage":
        print("\n垃圾检测完成")
    elif model_code == "001fire":
        print("\n火灾检测完成")
    else:
        print("\n检测完成")
    
    return detection_result

async def detect_image(image_path, model_code="003faceDetect"):
    """
    异步检测图片并返回结果
    
    参数:
        image_path (str): 图片路径
        model_code (str): 模型编码
    
    返回:
        dict: 检测结果的JSON对象
    """
    try:
        # 检查图片文件是否存在
        if not os.path.exists(image_path):
            print(f"错误: 图片文件不存在 - {image_path}")
            return None
        
        print(f"正在上传图片: {image_path}")
        print(f"目标API: {_api_url}")
        print(f"使用模型编码: {model_code}")
        
        # 准备文件数据
        with open(image_path, 'rb') as f:
            image_data = f.read()
        
        # 构建multipart/form-data请求
        async with aiohttp.ClientSession() as session:
            data = aiohttp.FormData()
            data.add_field('file', 
                          image_data, 
                          filename=os.path.basename(image_path), 
                          content_type='image/jpeg')
            data.add_field('model_code', model_code)
            
            # 发送POST请求
            async with session.post(_api_url, data=data) as response:
                # 检查响应状态
                response.raise_for_status()
                
                # 尝试解析JSON响应
                try:
                    result = await response.json()
                    return result
                except json.JSONDecodeError:
                    print(f"警告: 无法解析响应为JSON，原始响应内容: {await response.text()}")
                    return {"raw_response": await response.text()}
    
    except aiohttp.ClientError as e:
        print(f"请求出错: {e}")
        return None
    except Exception as e:
        print(f"发生错误: {e}")
        return None

async def run_async_demo():
    """
    运行异步演示示例
    """
    print("[异步垃圾检测示例]")
    garbage_image_path = r".\images\002garbage\test_garbage1.jpg"
    
    # 使用异步方法检测垃圾
    result = await detect_image(garbage_image_path, model_code="002garbage")
    
    # 打印检测结果
    print_detection_result(result)
    
    # 保存结果到JSON文件
    if result:
        # 生成保存文件名
        base_name = os.path.splitext(os.path.basename(garbage_image_path))[0]
        if not os.path.exists("./detect_out"):
            os.makedirs("./detect_out", exist_ok=True)
        json_file = f".\detect_out\detection_result_{base_name}.json"
        
        # 保存JSON文件
        with open(json_file, 'w', encoding='utf-8') as f:
            json.dump(result, f, ensure_ascii=False, indent=2)
        
        print(f"\n垃圾检测结果已保存到: {json_file}")
    
    print("\n异步垃圾检测完成")

if __name__ == "__main__":
    print("===== VisionForge SDK 演示程序 =====\n")
    print("1. 001火灾检测示例")
    print("2. 002垃圾检测示例")
    print("3. 003人脸检测示例\n")
    
    # 人脸检测示例
    print("[人脸检测示例]")
    face_image_path = r".\images\003faceDetect\test_face.jpg"
    detect_and_save_result(face_image_path, model_code="003faceDetect")
    
    print("\n" + "="*50 + "\n")
    
    # 火灾检测示例
    print("[火灾检测示例]")
    fire_image_path = r".\images\001fire\test1.jpg"
    detect_and_save_result(fire_image_path, model_code="001fire")
    
    print("\n" + "="*50 + "\n")
    
    # 垃圾检测示例（同步方式）
    print("[垃圾检测示例 (同步方式)]")
    garbage_image_path = r".\images\002garbage\test_garbage1.jpg"
    detect_and_save_result(garbage_image_path, model_code="002garbage")
    
    print("\n" + "="*50 + "\n")
    
    # 垃圾检测示例（异步方式）
    print("[垃圾检测示例 (异步方式)]")
    # 运行异步垃圾检测示例
    asyncio.run(run_async_demo())
    
    print("\n所有检测演示完成!")